﻿//++
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// Module Name:
//
//    AddEditNotificationRuleDialogTest.cs
//
// Abstract:
//    
//    Unit tests for the add/edit dialog.
//
// Classes:
//
//    Microsoft.EnhancedReminders.OutlookAddIn.UnitTests.AddEditNotificationRuleDialogTest
//
//--

using System;
using System.Collections.Generic;
using System.Windows.Controls;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.OfficeCommunicationsServer.Applications.Common;

using TestHelpers = Microsoft.EnhancedReminders.UnitTests.Helpers;

namespace Microsoft.EnhancedReminders.OutlookAddIn.UnitTests
{     
    /// <summary>
    ///This is a test class for AddEditNotificationRuleDialogTest and is intended
    ///to contain all AddEditNotificationRuleDialogTest Unit Tests
    ///</summary>
    [TestClass()]
    public class AddEditNotificationRuleDialogTest
    {
        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        /// Verify the add/edit dialog launches in the correct state.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void VerifyCorrectConditionIsSelected()
        {
            NotificationRuleItem editRule = CreateEditRule("test rule", /*people condition*/1);
          
            AddEditNotificationRuleDialog_Accessor target = 
                new AddEditNotificationRuleDialog_Accessor(editRule, /*showActionPage*/false, CreateMockOutlookApplication());

            Assert.IsTrue(target.peopleCheckBox.IsChecked.Value, "People checkbox should be selected");

            Assert.AreEqual(target.peopleTextBlock.Background, ConditionData_Accessor.HighlightConditionColor, "People condition should be highlighted");

            Assert.IsFalse(target.timeCheckBox.IsChecked.Value, "Time checkbox unchecked");
            Assert.IsFalse(target.statusCheckBox.IsChecked.Value, "Status checkbox unchecked");

            Assert.AreEqual("test rule", target.nameTextBox.Text, "Rule name should be displayed");

            // "Finish" button is not enabled because the people condition is unpopulated.
            Assert.IsFalse(AddEditNotificationRuleDialog_Accessor.FinishCommand.CanExecute(this, target.finishButton), "Finish button is not enabled");
        }

        /// <summary>
        /// Verify selecting (by checking its checkbox) a different condition (a) also displays the 
        /// highlighted condition and (b) results in the rule being saved with new value.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void VerifySelectingANewCondition()
        {
            NotificationRuleItem editRule = CreateEditRule("test rule", /*time condition*/0);

            AddEditNotificationRuleDialog_Accessor target =
                new AddEditNotificationRuleDialog_Accessor(editRule, /*showActionPage*/false, CreateMockOutlookApplication());

            // Time condition should be checked/highlighted.
            Assert.IsTrue(target.timeCheckBox.IsChecked.Value, "Time checkbox should be selected");
            Assert.AreEqual(target.timeTextBlock.Background, ConditionData_Accessor.HighlightConditionColor, "Time condition should be highlighted");

            // Now select the status condition.
            target.statusCheckBox.IsChecked = true;
            AddEditNotificationRuleDialog_Accessor.CheckBoxCommand.Execute(this, target.statusCheckBox);

            // Time condition should remain checked but unhighlighted, and the status checkbox selected/highlighted.
            Assert.IsTrue(target.timeCheckBox.IsChecked.Value, "Time checkbox should still be selected");
            Assert.AreNotEqual(target.timeTextBlock.Background, ConditionData_Accessor.HighlightConditionColor, "Time condition should no longer be highlighted");
            Assert.IsTrue(target.statusCheckBox.IsChecked.Value, "People checkbox should be selected");
            Assert.AreEqual(target.statusTextBlock.Background, ConditionData_Accessor.HighlightConditionColor, "Status condition should be highlighted");

            // Check that the "Finish" button is not enabled (as the selected status condition has no checkboxes
            // checked) - but don't execute as the dialog needs to be visible in order for "DialogResult" to be created.
            Assert.AreEqual(PresenceStates.None, ((NotificationStatusCondition)target.UpdatedRule.Conditions[2]).Presence, "No presence state should be selected");
            Assert.IsFalse(AddEditNotificationRuleDialog_Accessor.FinishCommand.CanExecute(this, target.finishButton), "Finish button is enabled");

            // Verify that the rule is updated correctly.
            Assert.IsFalse(object.ReferenceEquals(editRule, target.UpdatedRule), "Updated rule should have a new instance");
            Assert.IsNotNull(target.UpdatedRule, "target.UpdatedRule");
            Assert.AreEqual(target.UpdatedRule.Conditions.Count, editRule.Conditions.Count, "Unexpected number of conditions");
            Assert.IsTrue(target.UpdatedRule.Conditions[0].IsSelected, "Time condition should still be selected");
            Assert.IsFalse(target.UpdatedRule.Conditions[1].IsSelected, "People condition should be unselected");
            Assert.IsTrue(target.UpdatedRule.Conditions[2].IsSelected, "Status condition should be selected");
        }

        /// <summary>
        /// Verify that the rule name can be updated.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void VerifyEditingRuleName()
        {
            NotificationRuleItem editRule = CreateEditRule("test rule", /*time condition*/0);
            ((NotificationTimeCondition)editRule.Conditions[0]).TimeArray.Set(0, true); // Select a cell in the time grid to make it valid. 

            AddEditNotificationRuleDialog_Accessor target =
                new AddEditNotificationRuleDialog_Accessor(editRule, /*showActionPage*/false, CreateMockOutlookApplication());

            Assert.AreEqual("test rule", target.nameTextBox.Text, "Rule name should be displayed");

            // Update the rule name in the name textbox.
            target.nameTextBox.Text = "Updated test rule";

            Assert.IsTrue(AddEditNotificationRuleDialog_Accessor.FinishCommand.CanExecute(this, target.finishButton), "Finish button is enabled");

            Assert.IsFalse(object.ReferenceEquals(editRule, target._updatedRule), "Updated rule should have a new instance");

            Assert.AreEqual("Updated test rule", target._updatedRule.RuleName, "Rule name should be updated");
        }

        /// <summary>
        /// Verify that the "Finish" button is grayed out when the name field is empty.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void VerifyNameFieldMustBeNonEmptyToSave()
        {
            NotificationRuleItem editRule = CreateEditRule("test rule", /*time condition*/0);
            ((NotificationTimeCondition)editRule.Conditions[0]).TimeArray.Set(0, true); // Select a cell in the time grid to make it valid. 

            AddEditNotificationRuleDialog_Accessor target =
                new AddEditNotificationRuleDialog_Accessor(editRule, /*showActionPage*/false, CreateMockOutlookApplication());

            Assert.AreEqual("test rule", target.nameTextBox.Text, "Rule name should be displayed");

            Assert.IsTrue(AddEditNotificationRuleDialog_Accessor.FinishCommand.CanExecute(this, target.finishButton), "Finish button should be enabled");

            // Clear the rule name field.
            target.nameTextBox.Text = String.Empty;

            // Verify the "Finish" button is now unselected.
            Assert.IsFalse(AddEditNotificationRuleDialog_Accessor.FinishCommand.CanExecute(this, target.finishButton), "Finish button should no longer be enabled");
        }

        /// <summary>
        /// Verify that the "Finish" button is grayed out when time grid has no selected cells.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void VerifyTimeConditionIsValidBeforeSave()
        {
            NotificationRuleItem editRule = CreateEditRule("test rule", /*time condition*/0);

            NotificationTimeCondition timeCondition = editRule.Conditions[0] as NotificationTimeCondition;
            
            Assert.IsNotNull(timeCondition, "timeCondition");
            Assert.IsFalse(NotificationConditionHelper_Accessor.IsValidTimeCondition(timeCondition), "Time condition should not be valid");

            AddEditNotificationRuleDialog_Accessor target =
                new AddEditNotificationRuleDialog_Accessor(editRule, /*showActionPage*/false, CreateMockOutlookApplication());

            Assert.AreEqual("test rule", target.nameTextBox.Text, "Rule name field should be populated");

            Assert.IsFalse(AddEditNotificationRuleDialog_Accessor.FinishCommand.CanExecute(this, target.finishButton), "Finish button should not be enabled");

            // Make the time condition in the add/edit dialog valid by selecting a cell
            ((NotificationTimeCondition)target._updatedRule.Conditions[0]).TimeArray.Set(0, true);

            // Verify the "Finish" button is now enabled.
            Assert.IsTrue(AddEditNotificationRuleDialog_Accessor.FinishCommand.CanExecute(this, target.finishButton), "Finish button should now be enabled");
        }

        /// <summary>
        /// Verify the combo box items for selecting rule type are listed in the correct order and only 
        /// voicemails and calendar items enabled.
        /// </summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void VerifyRuleTypeComboBox()
        {
            NotificationRuleItem editRule = CreateEditRule("test rule", /*time condition*/0);

            ComboBox ruleType = new AddEditNotificationRuleDialog_Accessor(editRule, /*showActionPage*/false, CreateMockOutlookApplication()).ruleTypeComboBox;

            Assert.IsNotNull(ruleType, "ruleType");
            Assert.AreEqual(4, ruleType.Items.Count, "ruleType.Items.Count");

            VerifyItem(ruleType, MailboxType.Voicemail, 0, /*isEnabled*/true);
            VerifyItem(ruleType, MailboxType.CalendarItem, 1, /*isEnabled*/true);
            VerifyItem(ruleType, MailboxType.Email, 2, /*isEnabled*/false);
            VerifyItem(ruleType, MailboxType.Tasks, 3, /*isEnabled*/false);
        }
        
        /// <summary>
        /// Verify that any condition can be selected for voicemail rules.
        /// </summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void VerifyConditionsEnabledForVoiceMails()
        {
            NotificationRuleItem editRule = CreateEditRule("test rule", /*time condition*/0);

            AddEditNotificationRuleDialog_Accessor target =
                new AddEditNotificationRuleDialog_Accessor(editRule, /*showActionPage*/false, CreateMockOutlookApplication());

            // Verify expected rule type.
            Assert.AreEqual(MailboxType.Voicemail, GetRuleTypeFromIndex(target.ruleTypeComboBox, target.RuleTypeSelectedIndex), 
                            "Voicemail rule type should be selected");

            // Verify all conditions can be checked/displayed.
            Assert.IsTrue(AddEditNotificationRuleDialog_Accessor.CheckBoxCommand.CanExecute(target.timeCheckBox, target.timeCheckBox), "timeCheckBox");
            Assert.IsTrue(target.timeTextBlock.IsEnabled, "timeTextBlock");
            Assert.IsTrue(AddEditNotificationRuleDialog_Accessor.CheckBoxCommand.CanExecute(target.peopleCheckBox, target.peopleCheckBox), "peopleCheckBox");
            Assert.IsTrue(target.peopleTextBlock.IsEnabled, "peopleTextBlock");
            Assert.IsTrue(AddEditNotificationRuleDialog_Accessor.CheckBoxCommand.CanExecute(target.statusCheckBox, target.statusCheckBox), "statusCheckBox");
            Assert.IsTrue(target.statusTextBlock.IsEnabled, "statusTextBlock");
        }

        /// <summary>
        /// Verify that only the time condition can be accessed for calendar items.
        /// </summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void VerifyConditionsEnabledForCalendarItems()
        {
            // Create a rule for calendar items.
            NotificationRuleItem editRule = CreateEditRule("test rule", /*time condition*/0);
            editRule.MailboxType = MailboxType.CalendarItem;

            AddEditNotificationRuleDialog_Accessor target =
                new AddEditNotificationRuleDialog_Accessor(editRule, /*showActionPage*/false, CreateMockOutlookApplication());

            // Verify expected rule type.
            Assert.AreEqual(MailboxType.CalendarItem, GetRuleTypeFromIndex(target.ruleTypeComboBox, target.RuleTypeSelectedIndex), 
                            "Calendar rule type should be selected");

            // Verify only the time condition can be checked/displayed.
            Assert.IsTrue(AddEditNotificationRuleDialog_Accessor.CheckBoxCommand.CanExecute(target.timeCheckBox, target.timeCheckBox), "timeCheckBox");
            Assert.IsTrue(target.timeTextBlock.IsEnabled, "timeTextBlock");
            Assert.IsFalse(AddEditNotificationRuleDialog_Accessor.CheckBoxCommand.CanExecute(target.peopleCheckBox, target.peopleCheckBox), "peopleCheckBox");
            Assert.IsFalse(target.peopleTextBlock.IsEnabled, "peopleTextBlock");
            Assert.IsFalse(AddEditNotificationRuleDialog_Accessor.CheckBoxCommand.CanExecute(target.statusCheckBox, target.statusCheckBox), "statusCheckBox");
            Assert.IsFalse(target.statusTextBlock.IsEnabled, "statusTextBlock");
        }

        /// <summary>
        /// Verify the appropriate conditions are accessible when the rule type is changed.
        /// </summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void VerifySwitchingRuleType()
        {
            // Create voicemail rule with people condition selected.
            NotificationRuleItem editRule = CreateEditRule("test rule", /*people condition*/1);

            AddEditNotificationRuleDialog_Accessor target =
                new AddEditNotificationRuleDialog_Accessor(editRule, /*showActionPage*/false, CreateMockOutlookApplication());

            // Verify expected rule type.
            Assert.AreEqual(MailboxType.Voicemail, GetRuleTypeFromIndex(target.ruleTypeComboBox, target.RuleTypeSelectedIndex), 
                            "Voicemail rule type should be selected");
            
            // Verify only the people checkbox is checked.
            Assert.IsFalse(target.timeCheckBox.IsChecked.Value, "timeCheckBox.IsChecked");
            Assert.IsTrue(target.peopleCheckBox.IsChecked.Value, "peopleCheckBox.IsChecked");
            Assert.IsFalse(target.statusCheckBox.IsChecked.Value, "statusCheckBox.IsChecked");
            
            // Verify all conditions can be checked/displayed.
            Assert.IsTrue(AddEditNotificationRuleDialog_Accessor.CheckBoxCommand.CanExecute(target.timeCheckBox, target.timeCheckBox), "timeCheckBox is enabled");
            Assert.IsTrue(target.timeTextBlock.IsEnabled, "timeTextBlock.IsEnabled");
            Assert.IsTrue(AddEditNotificationRuleDialog_Accessor.CheckBoxCommand.CanExecute(target.peopleCheckBox, target.peopleCheckBox), "peopleCheckBox is enabled");
            Assert.IsTrue(target.peopleTextBlock.IsEnabled, "peopleTextBlock.IsEnabled");
            Assert.IsTrue(AddEditNotificationRuleDialog_Accessor.CheckBoxCommand.CanExecute(target.statusCheckBox, target.statusCheckBox), "statusCheckBox is enabled");
            Assert.IsTrue(target.statusTextBlock.IsEnabled, "statusTextBlock.IsEnabled");

            // Switch to rule type calendar.  The property is bound to the combo box SelectedIndex value.
            target.RuleTypeSelectedIndex = 1;

            Assert.AreEqual(MailboxType.CalendarItem, GetRuleTypeFromIndex(target.ruleTypeComboBox, target.RuleTypeSelectedIndex), 
                            "Calendar rule type should be selected");

            // Verify that the people condition has been unchecked and time condition checked.
            Assert.IsTrue(target.timeCheckBox.IsChecked.Value, "calendar: timeCheckBox.IsChecked");
            Assert.IsFalse(target.peopleCheckBox.IsChecked.Value, "calendar: peopleCheckBox.IsChecked");
            Assert.IsFalse(target.statusCheckBox.IsChecked.Value, "calendar: statusCheckBox.IsChecked");

            Assert.IsTrue(AddEditNotificationRuleDialog_Accessor.CheckBoxCommand.CanExecute(target.timeCheckBox, target.timeCheckBox), "calendar: timeCheckBox is enabled");
            Assert.IsTrue(target.timeTextBlock.IsEnabled, "calendar: timeTextBlock.IsEnabled");
            Assert.IsFalse(AddEditNotificationRuleDialog_Accessor.CheckBoxCommand.CanExecute(target.peopleCheckBox, target.peopleCheckBox), "calendar: peopleCheckBox is enabled");
            Assert.IsFalse(target.peopleTextBlock.IsEnabled, "calendar: peopleTextBlock.IsEnabled");
            Assert.IsFalse(AddEditNotificationRuleDialog_Accessor.CheckBoxCommand.CanExecute(target.statusCheckBox, target.statusCheckBox), "calendar: statusCheckBox is enabled");
            Assert.IsFalse(target.statusTextBlock.IsEnabled, "calendar: statusTextBlock.IsEnabled");

            // Switch back to voicemail.
            target.RuleTypeSelectedIndex = 0;

            Assert.AreEqual(MailboxType.Voicemail, GetRuleTypeFromIndex(target.ruleTypeComboBox, target.RuleTypeSelectedIndex), 
                            "Voicemail rule type should be selected after switching from calendar.");

            // The time condition should now be checked.
            Assert.IsTrue(target.timeCheckBox.IsChecked.Value, "voicemail2: timeCheckBox.IsChecked");
            Assert.IsFalse(target.peopleCheckBox.IsChecked.Value, "voicemail2: peopleCheckBox.IsChecked");
            Assert.IsFalse(target.statusCheckBox.IsChecked.Value, "voicemail2: statusCheckBox.IsChecked");

            // All condition types should be accessible.
            Assert.IsTrue(AddEditNotificationRuleDialog_Accessor.CheckBoxCommand.CanExecute(target.timeCheckBox, target.timeCheckBox), "voicemail2: timeCheckBox is enabled");
            Assert.IsTrue(target.timeTextBlock.IsEnabled, "voicemail2: timeTextBlock.IsEnabled");
            Assert.IsTrue(AddEditNotificationRuleDialog_Accessor.CheckBoxCommand.CanExecute(target.peopleCheckBox, target.peopleCheckBox), "voicemail2: peopleCheckBox is enabled");
            Assert.IsTrue(target.peopleTextBlock.IsEnabled, "voicemail2: peopleTextBlock.IsEnabled");
            Assert.IsTrue(AddEditNotificationRuleDialog_Accessor.CheckBoxCommand.CanExecute(target.statusCheckBox, target.statusCheckBox), "voicemail2: statusCheckBox is enabled");
            Assert.IsTrue(target.statusTextBlock.IsEnabled, "voicemail2: statusTextBlock.IsEnabled");
        }

        /// <summary>
        /// Verify one or more conditions can be selected.
        /// </summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void VerifyMultipleConditions()
        {
            // Start with voicemail rule with both the people and status conditions selected.
            NotificationRuleItem editRule = CreateEditRule("test rule", /*people condition*/1);
            editRule.Conditions[2].IsSelected = true;

            AddEditNotificationRuleDialog_Accessor target =
                new AddEditNotificationRuleDialog_Accessor(editRule, /*showActionPage*/false, CreateMockOutlookApplication());

            // Verify the dialog loads with the people and status conditions checked.
            Assert.IsFalse(target.timeCheckBox.IsChecked.Value, "time checkbox");
            Assert.IsTrue(target.peopleCheckBox.IsChecked.Value, "people checkbox");
            Assert.IsTrue(target.statusCheckBox.IsChecked.Value, "status checkbox");

            // The first checked condition (in this case the peeople condition) should be visible.
            Assert.AreEqual(System.Windows.Visibility.Hidden, target.timePanel.Visibility, "time panel");
            Assert.AreEqual(System.Windows.Visibility.Visible, target.peoplePanel.Visibility, "people panel");
            Assert.AreEqual(System.Windows.Visibility.Hidden, target.statusPanel.Visibility, "status panel");         

            // None of the conditions have been initialised and so the "Finish" button should be grayed out.
            Assert.IsFalse(AddEditNotificationRuleDialog_Accessor.FinishCommand.CanExecute(target, target.finishButton),
                           "Finish button should not be enabled");

            // Initialize the checked conditions and verify the "Finish" button is now enabled.
            ((NotificationPeopleCondition)target._updatedRule.Conditions[1]).Contacts.Add(new ContactInfo(null, "1234", "Peter"));
            ((NotificationStatusCondition)target._updatedRule.Conditions[2]).Presence = PresenceStates.Available;
            Assert.IsTrue(AddEditNotificationRuleDialog_Accessor.FinishCommand.CanExecute(target, target.finishButton),
                          "Finish button should now be enabled");

            // Now check the time checkbox.
            target.timeCheckBox.IsChecked = true;
            AddEditNotificationRuleDialog_Accessor.CheckBoxCommand.Execute(target, target.timeCheckBox);

            // Conditions are again invalid as time has not been initialized
            Assert.IsFalse(AddEditNotificationRuleDialog_Accessor.FinishCommand.CanExecute(target, target.finishButton),
                           "Finish button should not be enabled for an invalid time condition");

            // Modify the time grid to validate.
            ((NotificationTimeCondition)target._updatedRule.Conditions[0]).TimeArray[0] = true;
            Assert.IsTrue(AddEditNotificationRuleDialog_Accessor.FinishCommand.CanExecute(target, target.finishButton),
                          "Finish button should now be enabled as all three conditions are checked and valid");

            // Uncheck all conditions
            target.timeCheckBox.IsChecked = false;
            AddEditNotificationRuleDialog_Accessor.CheckBoxCommand.Execute(target, target.timeCheckBox);
            target.peopleCheckBox.IsChecked = false;
            AddEditNotificationRuleDialog_Accessor.CheckBoxCommand.Execute(target, target.peopleCheckBox);
            target.statusCheckBox.IsChecked = false;
            AddEditNotificationRuleDialog_Accessor.CheckBoxCommand.Execute(target, target.statusCheckBox);

            // conditions are invalid
            Assert.IsFalse(AddEditNotificationRuleDialog_Accessor.FinishCommand.CanExecute(target, target.finishButton),
                           "Finish button should not be enabled when no conditions are checked");
        }

        /// <summary>
        /// Ensure the "Next >" button is not enabled if the selected conditions are invalid.
        /// </summary>
        /// <remarks>Live Communications Team #134967</remarks>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void VerifyInvalidConditionsDeactivatesNextButton()
        {
            NotificationRuleItem editRule = CreateEditRule("test rule", /*status condition*/2);
            editRule.MailboxType = MailboxType.Voicemail;

            AddEditNotificationRuleDialog_Accessor target =
                new AddEditNotificationRuleDialog_Accessor(editRule, /*showActionPage*/false, CreateMockOutlookApplication());

            NotificationStatusCondition statusCondition = 
                Helpers.AssertCast<NotificationStatusCondition>(target.UpdatedRule.Conditions[2]);

            // Select status condition to simulate the bug.
            statusCondition.IsSelected = true;

            // "Next >" should be grayed out because status is none
            Assert.IsFalse(NotificationConditionHelper_Accessor.VerifyConditions(target.UpdatedRule));
            Assert.IsFalse(AddEditNotificationRuleDialog_Accessor.NextCommand.CanExecute(target, target.nextButton),
                           "Next button should not be enabled for an invalid time condition");

            // Select a presence status 
            statusCondition.Presence |= PresenceStates.Available;

            // Data on the conditions page should be valid and the "Next >" button should be enabled.
            Assert.IsTrue(NotificationConditionHelper_Accessor.VerifyConditions(target.UpdatedRule));
            Assert.IsTrue(AddEditNotificationRuleDialog_Accessor.NextCommand.CanExecute(target, target.nextButton),
                           "Next button should not be enabled for an invalid time condition");
        }

        /// <summary>
        /// Verify that when a new rule is created, SMS channels do not appear in the join now channel list
        /// and do appear in the notification channel list.
        /// </summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void TestCreatingNewRulePopulatesJoinNowChannelsCorrectly()
        {
            AddEditNotificationRuleDialog_Accessor target =
                new AddEditNotificationRuleDialog_Accessor(null, /*showActionPage*/false, CreateMockOutlookApplication());

            bool foundSms = false;
            foreach (NotificationChannel channel in target.UpdatedRule.NotificationChannels.Channels)
            {
                if (channel.NotificationChannelType == NotificationChannelType.SMS)
                {
                    foundSms = true;
                    break;
                }
            }

            // Confirm that the master channels list contains an SMS channel and that it appears
            // in the notification channel list.
            Assert.IsTrue(foundSms, "foundSms should be true for notification channels.");

            // Confirm that the join now channel list does not contain an SMS channel.
            Assert.IsTrue(target.UpdatedRule.JoinNowChannels.Channels.Count > 0, "Expecting >0 join now channels");
            foreach (NotificationChannel channel in target.UpdatedRule.JoinNowChannels.Channels)
            {
                if (channel.NotificationChannelType == NotificationChannelType.SMS)
                {
                    Assert.Fail("SMS channels should not appear in the join-now channel list");
                    break;
                }
            }
        }

        /// <summary>
        /// Helper method to create a mock Outlook application which stores the master channels.
        /// </summary>
        private static IOutlookApplication CreateMockOutlookApplication()
        {
            // Create a mock list of master channels with a channel enabled.
            List<NotificationChannel> masterChannels = new List<NotificationChannel>();
            masterChannels.Add(new NotificationChannel(NotificationChannelType.Communicator, "Communicator", "foo@bar.com"));
            masterChannels[0].IsEnabled = true;

            // Include an SMS channel for testing join now scenarios
            masterChannels.Add(new NotificationCustomChannel(NotificationChannelType.SMS, "SMS", "1234@foo.bar.com"));
            masterChannels[1].IsEnabled = true;

            // Save the channels to the mock Outlook store.
            NotificationStorageData storage = new NotificationStorageData(new NotificationChannelList(masterChannels), new NotificationRules());
            MockAttachments attachments = new MockAttachments(typeof(NotificationStorageData));
            OutlookUtils_Accessor.SaveAttachment(attachments, storage);

            return new MockApplication(new MockStorageItem(attachments));
        }

        /// <summary>
        /// Helper method to verify an item in the rule type combo box list.
        /// </summary>
        private static void VerifyItem(ComboBox ruleSelector, MailboxType expectedType, int index, bool isEnabled)
        {
            Assert.IsNotNull(ruleSelector, "ruleSelector");

            ComboBoxItem item = (ComboBoxItem)(ruleSelector.Items[index]);

            Assert.AreEqual(expectedType, GetRuleTypeFromIndex(ruleSelector, index), "Unexpected rule type");
            Assert.AreEqual(isEnabled, item.IsEnabled, "unexpected value for item.IsEnabled");
        }

        /// <summary>
        /// Helper method to return the MailBoxType value for an entry in the rule type combo box list.  This
        /// method uses the descriptor for each entry in the combo box to map to the correct MailBoxType (thus
        /// validating the description is as expected for each entry).
        /// </summary>
        private static MailboxType GetRuleTypeFromIndex(ComboBox ruleSelector, int index)
        {
            Assert.IsNotNull(ruleSelector, "ruleSelector");
            Assert.IsNotNull(ruleSelector.Items, "ruleSelector.Items");
            Assert.IsTrue(index >= 0 && index < ruleSelector.Items.Count, "index");

            ComboBoxItem item = Helpers.AssertCast<ComboBoxItem>(ruleSelector.Items[index]);
            StackPanel stackPanel = Helpers.AssertCast<StackPanel>(item.Content);

            Assert.AreEqual(2, stackPanel.Children.Count, "stackPanel.Children.Count");

            string itemText = Helpers.AssertCast<TextBlock>(stackPanel.Children[1]).Text;

            if (itemText == Properties.Resources.RulesDialogNewVoiceMails)
            {
                return MailboxType.Voicemail;
            }
            else if (itemText == Properties.Resources.RulesDialogCalendarItems)
            {
                return MailboxType.CalendarItem;
            }
            else if (itemText == Properties.Resources.RulesDialogNewEMails)
            {
                return MailboxType.Email;
            }
            else if (itemText == Properties.Resources.RulesDialogTasks)
            {
                return MailboxType.Tasks;
            }

            Assert.Fail("No match for itemText");

            return MailboxType.Tasks; // Return a non-default value.
        }

        /// <summary>
        /// Helper method to create a rule to be edited.
        /// </summary>
        /// <param name="name">The rule name.</param>
        /// <param name="selectedCondition">The condition to be selected.  Note that the condition will be unpopulated.</param>
        /// <returns>
        /// A rule instance that can be used in the add/edit dialog.
        /// </returns>
        private static NotificationRuleItem CreateEditRule(string name, int selectedCondition)
        {
            Assert.IsTrue(selectedCondition >= 0 && selectedCondition < 3, "selectedCondition");

            NotificationRuleItem rule = new NotificationRuleItem(MailboxType.Voicemail, name, DateTime.Now, TestHelpers.CreateDummyChannels());
            
            Assert.IsNotNull(rule.Conditions, "rule1.Conditions");
            Assert.IsTrue(rule.Conditions.Count == 3, "rule.Conditions.Count");
            
            rule.Conditions[selectedCondition].IsSelected = true;                    
           
            return rule;
        }
    }
}
